package com.team.cloudsharing.service.management;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.team.cloudsharing.dao.actionlog.ActionLogDAO;
import com.team.cloudsharing.dao.actionlog.ActionLogDO;
import com.team.cloudsharing.dao.file.FileDAO;
import com.team.cloudsharing.dao.file.FileDO;
import com.team.cloudsharing.dao.folder.FolderDAO;
import com.team.cloudsharing.dao.folder.FolderDO;
import com.team.cloudsharing.dao.sharefolder.ShareFolderDAO;
import com.team.cloudsharing.dao.sharefolder.ShareFolderDO;
import com.team.cloudsharing.dao.user.UserDAO;
import com.team.cloudsharing.dao.user.UserDO;
import com.team.cloudsharing.dto.Document;
import com.team.cloudsharing.dto.File;
import com.team.cloudsharing.dto.SharingInfo;
import com.team.cloudsharing.service.file.FileService;
import com.team.cloudsharing.ultis.Constant;

@Service("manageService")
public class ManageServiceImpl implements ManageService{
	
	@Autowired
	FolderDAO folderDAO;
	
	@Autowired
	FileDAO fileDAO;
	
	@Autowired
	UserDAO userDAO;
	
	@Autowired
	ShareFolderDAO shareFolderDAO;
	
	@Autowired 
	ActionLogDAO actionLogDAO;
	
	@Autowired
	FileService fileService;

	@Override
	public List<Document> getListDocument(String userEmail, String path, String trashStatus) {
		List<Document> listDocuments = new ArrayList<Document>();
		if (path != null || path != ""){
			List<Document> listFoldersForCheckIfEmpty = getListFolder(userEmail, path, trashStatus);
			if (listFoldersForCheckIfEmpty.size() == 0){
				String[] pathSplit = path.split(Constant.SUFFIX);
				String shareFolderName = pathSplit[0];
				UserDO userDO = userDAO.findUserByUserEmail(userEmail);
				ShareFolderDO shareFolderDO = shareFolderDAO.findShareFolderByFolderNameAndUserId(shareFolderName, userDO); 
				if (shareFolderDO != null){
					FolderDO folderDOShared = folderDAO.findFolderById(shareFolderDO.getFolderDO().getFolderId());
					if (! userEmail.equals(folderDOShared.getUserDO().getUserEmail())){
						String realPath = ""; 
						if (folderDOShared.getFolderPath().isEmpty()){
							realPath = folderDOShared.getFolderName();
						}
						else{
							realPath = folderDOShared.getFolderPath() + Constant.SUFFIX + folderDOShared.getFolderName();
						}
						for (int i = 1; i < pathSplit.length; i++){
							realPath = realPath + Constant.SUFFIX + pathSplit[i];
						}
						path = realPath;
						userEmail = folderDOShared.getUserDO().getUserEmail();
					}
				}
			}
		}
			
		List<Document> listFolders = getListFolder(userEmail, path, trashStatus);
		
		listDocuments.addAll(listFolders);
		
		if (path == null || path == ""){
			List<Document> listFoldersWasShared = getListFoldersWasShared(userEmail, trashStatus);
			if (listFoldersWasShared != null) {
				listDocuments.addAll(listFoldersWasShared);
			}
		}

		List<Document> listFile = getListFile(userEmail, path, trashStatus);
		listDocuments.addAll(listFile);
		
		return listDocuments;
	}
	
	private List<Document> getListFoldersWasShared(String userEmail, String trashStatus){
		List<Document> listFoldlersWasShared = new ArrayList<Document>();
		UserDO userDOWasShared = userDAO.findUserByUserEmail(userEmail);
		List<ShareFolderDO> listShareFolderDOs = shareFolderDAO.findAllShareFolderByUserId(userDOWasShared);
		Document document = null;
		FolderDO folderDO = null;
		if (listShareFolderDOs != null){
			for (ShareFolderDO shareFolderDO : listShareFolderDOs) {
				folderDO = shareFolderDO.getFolderDO();
				if (folderDO.isSharedFolder() == true && shareFolderDO.isShareFolderInTrash() == false){
					document = convertFolderDOtoDocument(folderDO);
					document.setDocumentName(shareFolderDO.getUserFolderName());
					document.setDocumentPath(null);
					listFoldlersWasShared.add(document);
				}
			}
		}
		return listFoldlersWasShared;
	}
	
	private List<Document> getListFolder(String userEmail, String path, String trashStatus) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<FolderDO> listFolderDOs = folderDAO.findAllFolderByFolderPathAndUserId(path, userDO, trashStatus);
		List<Document> listFolders = new ArrayList<Document>();
		Document document;
		for(FolderDO folderDO : listFolderDOs){
			document = convertFolderDOtoDocument(folderDO);
			document.setUserEmail(userEmail);
			listFolders.add(document);
		}
		return listFolders;
	}

	@Override
	public List<Document> getListFile(String userEmail, String path, String trashStatus) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		FolderDO folderDO = null;
		if (path != null && path != ""){
			//Split path and find FolderName and folderPath
			String[] folderNameAndFolderPath = fileService.splitFolderNameAndFolderPathInFilePath(path);
			folderDO = folderDAO.findFolderByFolderNameAndFolderPathAndUserId(folderNameAndFolderPath[0], folderNameAndFolderPath[1], userDO);
		}
		else{
			folderDO = folderDAO.findROOTFolderOfUser(userDO);
		}
		List<FileDO> listFileDOs = fileDAO.findAllFileInFolder(folderDO, trashStatus);
		List<Document> listFiles = new ArrayList<Document>();
		Document document;
		for(FileDO fileDO : listFileDOs){
			document = convertFileDOtoDocument(fileDO);
			document.setUserEmail(userEmail);
			listFiles.add(document);
		}
		return listFiles;
	}
	
	@Override
	public List<Document> searchDocument(String userEmail, String searchQuery) {
		List<Document> listFolder = searchFolder(userEmail, searchQuery);
		List<Document> listFile = searchFile(userEmail, searchQuery);
		
		List<Document> listDocument = new ArrayList<Document>();
		listDocument.addAll(listFolder);
		listDocument.addAll(listFile);
		return listDocument;
	}
	
	private List<Document> searchFolder(String userEmail, String searchQuery) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<FolderDO> listFolderDOs = folderDAO.findFolderByFolderNameAndUserId(searchQuery, userDO);
		List<Document> listFolders = new ArrayList<Document>();
		for(FolderDO folderDO : listFolderDOs){
			System.out.println(folderDO.getFolderName());
			listFolders.add(convertFolderDOtoDocument(folderDO));
		}
		return listFolders;
	}
	
	private List<Document> searchFile(String userEmail, String searchQuery) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<FileDO> listFileDOs = fileDAO.findFileByFileNameAndUserId(searchQuery, userDO);
		List<Document> listFiles = new ArrayList<Document>();
		for(FileDO fileDO : listFileDOs){
			listFiles.add(convertFileDOtoDocument(fileDO));
		}
		return listFiles;
	}

	@Override
	public List<Document> getListDocumentInTrash(String userEmail, String trashStatus) {
		List<Document> listFolder = getListFolderInTrash(userEmail, trashStatus);
		List<Document> listFile = new ArrayList<Document>();
		List<Document> listFileInFolder = new ArrayList<Document>();
		//Get all file in trash in ROOT folder
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		FolderDO folderROOT = folderDAO.findROOTFolderOfUser(userDO);
		listFileInFolder.addAll(getListFileInTrash(folderROOT, trashStatus));
		if (listFileInFolder.size() > 0){
			listFile.addAll(listFileInFolder);
		}
		//Get all file in Trash
		List<Document> listFolderNoneTrash = getListFolderInTrash(userEmail, "");
		for(Document document: listFolderNoneTrash){
			listFileInFolder.clear();
			FolderDO folderDO = folderDAO.findFolderById(document.getDocumentId());
			//If folder is moved to trash => don't get list file
			if (folderDO != null && folderDO.isFolderInTrash() == false){
				listFileInFolder.addAll(getListFileInTrash(folderDO, trashStatus));
				if (listFileInFolder.size() > 0){
					listFile.addAll(listFileInFolder);
				}
			}
		}
		//Get all file and folder was shared share in trash
		List<Document> listDocumentWasSharedInTrash = getListDocumentWasSharedInTrash(userEmail, trashStatus);
		
		List<Document> listDocumentShareInTrash = getListDocumentShareInTrash(userEmail, trashStatus);
		
		List<Document> listDocument = new ArrayList<Document>();
		listDocument.addAll(listFolder);
		listDocument.addAll(listDocumentWasSharedInTrash);
		listDocument.addAll(listDocumentShareInTrash);
		listDocument.addAll(listFile);
		return listDocument;
	}
	
	@Override
	public List<Document> getListDocumentInTrashForPC(String userEmail, String trashStatus) {
		List<Document> listFolder = getListFolderInTrash(userEmail, trashStatus);
		List<Document> listFile = new ArrayList<Document>();
		List<Document> listFileInFolder = new ArrayList<Document>();
		//Get all file in trash in ROOT folder
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		FolderDO folderROOT = folderDAO.findROOTFolderOfUser(userDO);
		listFileInFolder.addAll(getListFileInTrash(folderROOT, trashStatus));
		if (listFileInFolder.size() > 0){
			listFile.addAll(listFileInFolder);
		}
		//Get all file in Trash
		List<Document> listFolderNoneTrash = getListFolderInTrash(userEmail, "");
		for(Document document: listFolderNoneTrash){
			listFileInFolder.clear();
			FolderDO folderDO = folderDAO.findFolderById(document.getDocumentId());
			//If folder is moved to trash => don't get list file
			if (folderDO != null && folderDO.isFolderInTrash() == false){
				listFileInFolder.addAll(getListFileInTrash(folderDO, trashStatus));
				if (listFileInFolder.size() > 0){
					listFile.addAll(listFileInFolder);
				}
			}
		}
		
		List<Document> listDocument = new ArrayList<Document>();
		listDocument.addAll(listFolder);
		listDocument.addAll(listFile);
		return listDocument;
	}
	
	private List<Document> getListFolderInTrash(String userEmail, String trashStatus){
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<FolderDO> listFolderDOs = folderDAO.findAllFolderWithTrashStatusByUserId(userDO, trashStatus);
		List<Document> listFolders = new ArrayList<Document>();
		for(FolderDO folderDO : listFolderDOs){
			//If folder parent is moved to trash => don't get folder
			FolderDO folderDOParent = folderDAO.findFolderById(folderDO.getFolderIdParent());
			if (folderDOParent.isFolderInTrash() == false){
				listFolders.add(convertFolderDOtoDocument(folderDO));
			}
		}
		return listFolders;
	}
	
	private List<Document> getListDocumentShareInTrash(String userEmail, String trashStatus){
		List<Document> listDocumentShareInTrashs = new ArrayList<Document>();
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<ShareFolderDO> listShareFolderDOs = shareFolderDAO.findAllShareFolderByUserId(userDO);
		FolderDO folderDO = null;
		for (ShareFolderDO shareFolderDO : listShareFolderDOs) {
			if (shareFolderDO.isShareFolderInTrash()){
				folderDO = new FolderDO();
				folderDO.setFolderName(shareFolderDO.getUserFolderName());
				folderDO.setFolderPath(Constant.EMPTY_PATH);
				folderDO.setFolderIdParent(-1L);
				folderDO.setSharedFolder(true);
				folderDO.setFolderInTrash(shareFolderDO.isShareFolderInTrash());
				folderDO.setUserDO(userDO);
				listDocumentShareInTrashs.add(convertFolderDOtoDocument(folderDO));
			}
		}
		return listDocumentShareInTrashs;
	}
	
	private List<Document> getListDocumentWasSharedInTrash(String userEmail, String trashStatus){
		List<Document> listDocumentShareInTrashs = new ArrayList<Document>();
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<ShareFolderDO> listShareFolderDOs = shareFolderDAO.findAllShareFolderByUserId(userDO);
		for (ShareFolderDO shareFolderDO : listShareFolderDOs) {
			FolderDO folderDO = shareFolderDO.getFolderDO();
			listDocumentShareInTrashs.addAll(getListDocumentChildShareInTrash(folderDO.getFolderId(), trashStatus));
		}
		return listDocumentShareInTrashs;
	}
	
	private List<Document> getListDocumentChildShareInTrash(long folderId, String trashStatus){
		List<Document> listDocumentChildShareInTrash = new ArrayList<Document>();
		FolderDO folderDOCurrent = folderDAO.findFolderById(folderId);
		List<FolderDO> listFolderDOInFolder = folderDAO.findAllFolderInFolder(folderDOCurrent);
		if (listFolderDOInFolder.size() > 0){
			for (FolderDO folderDO : listFolderDOInFolder) {
				if (folderDO.isFolderInTrash() == false){
					listDocumentChildShareInTrash.addAll(getListDocumentChildShareInTrash(folderDO.getFolderId(), trashStatus));
				}
				else{
					listDocumentChildShareInTrash.add(convertFolderDOtoDocument(folderDO));
				}
			}
		}
		listDocumentChildShareInTrash.addAll(getListFileInTrash(folderDOCurrent, trashStatus));
		return listDocumentChildShareInTrash;
	}
	
	private List<Document> getListFileInTrash(FolderDO folderDO, String trashStatus){
		List<FileDO> listFileDOs = fileDAO.findAllFileInFolder(folderDO, trashStatus);
		List<Document> listFiles = new ArrayList<Document>();
		if (listFileDOs != null) {
			for(FileDO fileDO : listFileDOs){
				listFiles.add(convertFileDOtoDocument(fileDO));
			}
		}
		return listFiles;
	}
	
	private Document convertFolderDOtoDocument(FolderDO folderDO){
		Document document = new Document();
		document.setUserEmail(folderDO.getUserDO().getUserEmail());
		document.setDocumentCapacity(0L);
		document.setDocumentPermision(-1);
		document.setDocumentId(folderDO.getFolderId());
		document.setDocumentType(Constant.DOC_FOLDER);
		document.setDocumentName(folderDO.getFolderName());
		if (folderDO.getFolderPath() == null) {
			folderDO.setFolderPath("");
		}
		document.setDocumentPath(folderDO.getFolderPath());
		document.setDocumentUrl(folderDO.getFolderUrl());
		document.setCreateDate(folderDO.getDateCreate());
		document.setDocumentInTrash(folderDO.isFolderInTrash());
		document.setDocumentPermision(folderDO.getFolderPermission());
		document.setSharedFolder(folderDO.isSharedFolder());
		document.setModifiedUserId(0L);
		document.setModifiedDate(new Date());
		return document;
	}
	
	private Document convertFileDOtoDocument(FileDO fileDO){
		Document document = new Document();
		document.setUserEmail(fileDO.getFolderDO().getUserDO().getUserEmail());
		document.setDocumentId(fileDO.getFileId());
		document.setDocumentType(Constant.DOC_FILE);
		document.setDocumentName(fileDO.getFileName());
		document.setDocumentUrl(fileDO.getFileUrl());
		document.setDocumentCapacity(fileDO.getFileCapacity());
		if (fileDO.getFilePath() == null) {
			fileDO.setFilePath("");
		}
		document.setDocumentPath(fileDO.getFilePath());
		document.setCreateDate(fileDO.getDateCreate());
		document.setDocumentInTrash(fileDO.isFileInTrash());
		document.setDocumentPermision(fileDO.getFilePermission());
		document.setFileBackup(fileDO.isFileBackup());
		document.setModifiedDate(fileDO.getModifiedDate());
		if (fileDO.getModifiedUserId() == null) {
			fileDO.setModifiedUserId(0L);
		}
		document.setModifiedUserId(fileDO.getModifiedUserId());
		return document;
	}

	@Override
	public List<File> getListImages(String userEmail,long offset) {
		
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<File> listImages = new ArrayList<File>();
		if(userDO != null){
			List<FolderDO> listFolderDO = folderDAO.findAllFolderByUserId(userDO);
			if(listFolderDO != null){
				List<File> listImagesOfEachFolder = new ArrayList<File>();
				for(FolderDO folderDO : listFolderDO){
					listImagesOfEachFolder = getAllImagesOfEachFolder(folderDO,offset);
					listImages.addAll(listImagesOfEachFolder);
				}
			}
		}

		return listImages;
	}

	private List<File> getAllImagesOfEachFolder(FolderDO folderDO, long offset) {
		
		List<File> allImagesOfEachFolder = null;
		
		List<FileDO> listImagesDOofEachFolder = null;
		
		listImagesDOofEachFolder = fileDAO.findAllImagesInFolder(folderDO,"false",offset);
		if(listImagesDOofEachFolder != null){
			allImagesOfEachFolder = new ArrayList<File>();
			for(FileDO imageDO : listImagesDOofEachFolder){
				allImagesOfEachFolder.add(ConvertImageDOToImageFile(imageDO));
			}
		}
		return allImagesOfEachFolder;
	}

	private File ConvertImageDOToImageFile(FileDO imageDO) {
		
		File image = new File();
		image.setDateCreate(imageDO.getDateCreate());
		image.setFileCapacity(imageDO.getFileCapacity());
		image.setFileName(imageDO.getFileName());
		image.setFilePath(imageDO.getFilePath());
		image.setUserEmail(imageDO.getFolderDO().getUserDO().getUserEmail());
		return image;
	}

	@Override
	public long getDocumentId(String userEmail, String folderPath,
			String folderName, String fileName) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		if (fileName != null && fileName != ""){
			return getFileId(userDO, folderPath, folderName, fileName);
		}
		else {
			return getFolderId(userDO, folderPath, folderName);
		}
	}

	private long getFolderId(UserDO userDO, String folderPath, String folderName) {
		return folderDAO.findFolderByFolderNameAndFolderPathAndUserId(folderName, folderPath, userDO).getFolderId();
	}

	private long getFileId(UserDO userDO, String folderPath, String folderName,
			String fileName) {
		FolderDO folderDO = folderDAO.findFolderByFolderNameAndFolderPathAndUserId(folderName, folderPath, userDO);
		if (folderDO == null){
			folderDO = folderDAO.findROOTFolderOfUser(userDO);
		}
		FileDO fileDO = fileDAO.findFileByFileNameInFolder(fileName, folderDO);
		
		//FileDO fileDO = fileDAO.findFileByFileNameAndFolder(fileName, folderDO);
		
		return fileDO.getFileId();
	}

	@Override
	public String checkStatus(String macAddress) {
		ActionLogDO actionLogDO = actionLogDAO.findActionLogByMacAddress(macAddress);
		if (actionLogDO != null) {
			if (actionLogDO.isStatus()) {
				return "true";
			}
			else {
				return "false";
			}
		}
		return "false";
	}

	@Override
	public void setStatus(String macAddress) {
		actionLogDAO.setStatusByMacAddress(macAddress);
	}

	@Override
	public List<SharingInfo> getSharingInfomation(String userEmail) {
		List<SharingInfo> shareInformation = new ArrayList<SharingInfo>();
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		List<ShareFolderDO> listShareFolderDO = shareFolderDAO.findAllShareFolderByUserId(userDO);
		SharingInfo sharingInfo = null;
		for (ShareFolderDO shareFolderDO : listShareFolderDO) {
			sharingInfo = new SharingInfo();
			sharingInfo.setFolderName(shareFolderDO.getUserFolderName());
			sharingInfo.setOwnerName(shareFolderDO.getFolderDO().getUserDO().getUserName());
			sharingInfo.setOwnerEmail(shareFolderDO.getFolderDO().getUserDO().getUserEmail());
			shareInformation.add(sharingInfo);
		}
		return shareInformation;
	}
}
